#include "quickjs-libc.h"
#include "quickjs.h"
#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <string>

std::map<std::string, std::string> jsObjectToMap(JSContext *ctx,
                                                 JSValue object) {
  std::map<std::string, std::string> result;
  JSPropertyEnum *properties = nullptr;
  uint32_t propertyCount = 0;
  if (JS_GetOwnPropertyNames(ctx, &properties, &propertyCount, object,
                             JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK) < 0) {
    return result;
  }
  for (uint32_t i = 0; i < propertyCount; i++) {
    JSAtom atom = properties[i].atom;
    const char *key_ = JS_AtomToCString(ctx, atom);
    std::string key = std::string(key_);

    JSValue propertyValue = JS_GetProperty(ctx, object, atom);
    const char *value_ = JS_ToCString(ctx, propertyValue);
    std::string value = std::string(value_);
    result[key] = value;
    // JS_FreeValue(ctx, key_);
    // JS_FreeValue(ctx, value_);
    // JS_FreeValue(ctx, propertyName);
    // JS_FreeValue(ctx, propertyValue);
  }
  js_free(ctx, properties);
  return result;
}

int main() {
  JSRuntime *rt = JS_NewRuntime();
  JSContext *ctx = JS_NewContext(rt);
  const char *script = "({key1: 'value1', key2: 'value2'})";
  JSValue value =
      JS_Eval(ctx, script, strlen(script), "es.js", JS_EVAL_TYPE_GLOBAL);

  if (JS_IsException(value)) {
    JS_FreeValue(ctx, value);
    JS_FreeContext(ctx);
    JS_FreeRuntime(rt);
    return 1;
  }

  // 将对象转换为 Map
  std::map<std::string, std::string> map = jsObjectToMap(ctx, value);

  // 输出 Map 的内容
  for (const auto &entry : map) {
    std::cout << entry.first << ": " << entry.second << std::endl;
  }

  // 释放资源
  JS_FreeValue(ctx, value);
  JS_FreeContext(ctx);
  JS_FreeRuntime(rt);

  return 0;
}